package socket.tcp.单聊;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 周宇
 * @create 2020-08-19 12:21
 * 创建服务器
 * 写出数据：输出流
 * 读取数据：输入流
 */
public class Server {
    private List<MyChannel> all = new ArrayList<MyChannel>();//保存多个客户端

    public static void main(String[] args) throws IOException {
        new Server().start();
    }

    private void start() throws IOException {
        ServerSocket server = new ServerSocket(8888);
        while (true) {
            Socket client = server.accept();//阻塞 等待连接
            MyChannel channel = new MyChannel(client);//放入通道
            all.add(channel);//统一管理

            new Thread(channel).start(); //一条道路
        }
    }

    /**
     * 一个客户端 一条道路
     * 1、输入流
     * 2、输出流
     * 3、接收数据
     * 4、发送数据
     */
    private class MyChannel implements Runnable {
        private DataInputStream dis;//接收数据
        private DataOutputStream dos;//发送数据
        private boolean isRunning = true;
        private String name;

        public MyChannel(Socket client) {
            try {
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());
                this.name = dis.readUTF();//接收数据
                this.send("欢迎您进入聊天室");
                sendOthers(this.name + "进入了聊天室", true);
            } catch (IOException e) {
                //e.printStackTrace();
                CloseUtil.closeAll(dis, dos);
                isRunning = false;
            }
        }

        /**
         * 读取数据
         * @return
         */
        private String receive() {
            String msg = "";//读取的消息保存到msg
            try {
                msg = dis.readUTF();
            } catch (IOException e) {
                //e.printStackTrace();
                CloseUtil.closeAll(dis);
                isRunning = false;
                all.remove(this); //移除自身
            }
            return msg;
        }

        /**
         * 发送数据
         */
        private void send(String msg) {
            if (null == msg || msg.equals("")) {
                return;
            }
            try {
                dos.writeUTF(msg);
                dos.flush();
            } catch (IOException e) {
                //e.printStackTrace();
                CloseUtil.closeAll(dos);
                isRunning = false;
                all.remove(this); //移除自身
            }
        }

        /**
         * 发送给其他客户端
         */
        private void sendOthers(String msg, boolean sys) {
            //是否为私聊 约定
            if (msg.startsWith("@") && msg.indexOf(":") > -1) { //私聊
                //获取name
                String name = msg.substring(1, msg.
                        indexOf(":"));
                String content = msg.substring
                        (msg.indexOf(":") + 1);
                for (MyChannel other : all) {
                    if (other.name.equals(name)) {
                        other.send
                                (this.name + " 对您悄悄地说:" + content);
                    }
                }
            } else {
                //遍历容器
                for (MyChannel other : all) {
                    if (other == this) {
                        continue;
                    }
                    if (sys) { //系统信息
                        other.send("系统信息:" + msg);
                    } else {
                        //发送其他客户端
                        other.send(this.name + " 对所有人说:" + msg);
                    }
                }
            }
        }

        //服务器一直读取数据 并发送给其他的客户端
        @Override
        public void run() {
            while(isRunning){
                //sendOthers(receive(),false);
                System.out.println(receive());
            }
        }
    }
}
